home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
NOVA - For the NeXT Workstation
/
NOVA - For the NeXT Workstation.iso
/
SourceCode
/
AdobeExamples
/
NX_Scroll
/
DrawingView.m
< prev
next >
Wrap
Text File
|
1992-12-19
|
12KB
|
521 lines
/*
* (a) (C) 1990 by Adobe Systems Incorporated. All rights reserved.
*
* (b) If this Sample Code is distributed as part of the Display PostScript
* System Software Development Kit from Adobe Systems Incorporated,
* then this copy is designated as Development Software and its use is
* subject to the terms of the License Agreement attached to such Kit.
*
* (c) If this Sample Code is distributed independently, then the following
* terms apply:
*
* (d) This file may be freely copied and redistributed as long as:
* 1) Parts (a), (d), (e) and (f) continue to be included in the file,
* 2) If the file has been modified in any way, a notice of such
* modification is conspicuously indicated.
*
* (e) PostScript, Display PostScript, and Adobe are registered trademarks of
* Adobe Systems Incorporated.
*
* (f) THE INFORMATION BELOW IS FURNISHED AS IS, IS SUBJECT TO
* CHANGE WITHOUT NOTICE, AND SHOULD NOT BE CONSTRUED
* AS A COMMITMENT BY ADOBE SYSTEMS INCORPORATED.
* ADOBE SYSTEMS INCORPORATED ASSUMES NO RESPONSIBILITY
* OR LIABILITY FOR ANY ERRORS OR INACCURACIES, MAKES NO
* WARRANTY OF ANY KIND (EXPRESS, IMPLIED OR STATUTORY)
* WITH RESPECT TO THIS INFORMATION, AND EXPRESSLY
* DISCLAIMS ANY AND ALL WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR PARTICULAR PURPOSES AND NONINFRINGEMENT
* OF THIRD PARTY RIGHTS.
*/
/*
* DrawingView.m
*
* This view represents the page that the image is drawn onto. It is
* a subview of the DocView. The DocView is the document view of
* the ClipView. This view's real size grows with the scale but the
* bounds always stays the same.
*
*
* Version: 2.0
* Author: Ken Fromm
* History:
* 03-07-91 Added this comment.
*/
#import "DrawingView.h"
#import "DrawingViewWraps.h"
#import "DocView.h"
#import "Graphic.h"
#import "ScrollApp.h"
#import <objc/List.h>
#import <appkit/Button.h>
#import <appkit/Control.h>
#import <appkit/Matrix.h>
#import <appkit/nextstd.h>
#import <dpsclient/dpsclient.h>
#import <dpsclient/wraps.h>
extern void initGparms();
extern void setGparms();
@implementation DrawingView
/*
* Allocate a gstate, set the clipping to NO because it will be clipped
* by the clip view.
*/
+newFrame:(NXRect *) frm
{
self = [super newFrame:frm];
drawUpath = [NXApp getUpathBuffer];
drawManner = UPATH;
return self;
}
- free
{
[self freeGraphics];
return [super free];
}
- setFieldsMode:(BOOL) mode
{
displayFields = eraseFields = mode;
return self;
}
- setTypeOfDrawing:sender
{
id matrixId;
drawFrame = ([sender selectedRow] == 1);
matrixId = [NXApp getStrokingMatrix];
[[matrixId cellAt:0 :0] setEnabled:drawFrame];
[[matrixId cellAt:1 :0] setEnabled:drawFrame];
matrixId = [NXApp getParameterMatrix];
[[matrixId cellAt:0 :0] setEnabled:!drawFrame];
[[matrixId cellAt:1 :0] setEnabled:!drawFrame];
[NXApp redrawAction:self];
return self;
}
- setSelectivity:sender
{
drawEverything = ([sender selectedRow] == 1);
[NXApp redrawAction:self];
return self;
}
- setDrawingManner:sender
{
drawManner = [sender selectedRow];
[NXApp redrawAction:self];
return self;
}
- setStroking:sender
{
drawCombined = ([sender selectedRow] == 1);
[NXApp redrawAction:self];
return self;
}
- setParameterSetting:sender
{
drawEveryPath = ([sender selectedRow] == 1);
[NXApp redrawAction:self];
return self;
}
-setDrawOrigin:(NXPoint *)origin
{
drawOrigin = *origin;
return self;
}
- freeGraphics
{
if (graphicsListId)
[graphicsListId freeObjects];
[graphicsListId free];
return self;
}
- insertList:listId
{
[self freeGraphics];
graphicsListId = listId;
return self;
}
- eraseFields:sender
{
id matrixId;
int i;
matrixId = [NXApp getTimingMatrix];
for (i= 0; i < [matrixId cellCount]; i++)
[[matrixId cellAt:i :0] setStringValue:""];
matrixId = [NXApp getStatusMatrix];
for (i= 0; i < [matrixId cellCount]; i++)
[[matrixId cellAt:i :0] setStringValue:""];
return self;
}
- displayFields:sender
{
id matrixId;
int i, ucache_values[5];
if (timing_info.num_draws)
{
matrixId = [NXApp getTimingMatrix];
[[matrixId cellAt:0 :0]
setFloatValue:timing_info.num_draws];
[[matrixId cellAt:1 :0]
setFloatValue:timing_info.drawingtime/timing_info.num_draws];
if (!drawFrame)
{
[[matrixId cellAt:2 :0]
setFloatValue:timing_info.num_fills/timing_info.num_draws];
[[matrixId cellAt:3 :0]
setFloatValue:timing_info.num_strokes/timing_info.num_draws];
}
else
[[matrixId cellAt:3 :0]
setFloatValue:timing_info.num_strokes/timing_info.num_draws];
[[matrixId cellAt:4 :0]
setFloatValue:timing_info.num_subpaths/timing_info.num_draws];
}
if (drawManner == UCACHE)
{
matrixId = [NXApp getStatusMatrix];
PSWUcachestatus(&ucache_values[0], &ucache_values[1],
&ucache_values[2], &ucache_values[3], &ucache_values[4]);
for (i= 0; i < [matrixId cellCount]; i++)
[[matrixId cellAt:i :0] setIntValue:ucache_values[i]];
}
/* Prepare for next time around. */
timing_info.num_fills = timing_info.num_strokes = 0;
timing_info.num_subpaths = timing_info.num_draws = 0;
timing_info.drawingtime = 0.0;
return self;
}
/*
* If the docview is zooming, then scale the drawing view.
*/
- mouseDown:(NXEvent *)event
{
NXPoint p;
p = event->location;
if ([superview isZooming])
{
displayFields = eraseFields = YES;
return [nextResponder scaleDrawView:self toPoint:&p];
}
return self;
}
/*
* Initialize the user path structure. Always include a ucache.
* If ucache is not used then start at the second entry in the op
* array and decrement num_ops by one.
*/
static void initUpath(UPath *aUpath)
{
aUpath->ops[0] = dps_ucache;
aUpath->num_ops = 1;
aUpath->pts[0] = 99999;
aUpath->pts[1] = 99999;
aUpath->pts[2] = -99999;
aUpath->pts[3] = -99999;
aUpath->num_pts = 4;
}
/*
* Increment the stroke count and stroke the existing path.
*/
static void strokeRedBook(int *strokes)
{
*strokes += 1;
PSstroke();
}
/*
* Call the appropriate wrap to construct the path. Not the recommended
* approach to drawing (user paths are). Made external so Graphic.m
* can make use of it.
*/
void makeRedBook(UPath *aUpath)
{
int i_op, i_pt;
i_pt = 4;
/* Skip the ucache operator. */
for (i_op = 1; i_op < aUpath->num_ops; i_op++)
{
switch (aUpath->ops[i_op])
{
case dps_moveto:
PSmoveto(aUpath->pts[i_pt], aUpath->pts[i_pt+1]);
i_pt += 2;
break;
case dps_rmoveto:
PSrmoveto(aUpath->pts[i_pt], aUpath->pts[i_pt+1]);
i_pt += 2;
break;
case dps_lineto:
PSlineto(aUpath->pts[i_pt], aUpath->pts[i_pt+1]);
i_pt += 2;
break;
case dps_rlineto:
PSrlineto(aUpath->pts[i_pt], aUpath->pts[i_pt+1]);
i_pt += 2;
break;
case dps_curveto:
PScurveto(aUpath->pts[i_pt], aUpath->pts[i_pt+1],
aUpath->pts[i_pt+2], aUpath->pts[i_pt+3],
aUpath->pts[i_pt+4], aUpath->pts[i_pt+5]);
i_pt += 6;
break;
case dps_rcurveto:
PSrcurveto(aUpath->pts[i_pt], aUpath->pts[i_pt+1],
aUpath->pts[i_pt+2], aUpath->pts[i_pt+3],
aUpath->pts[i_pt+4], aUpath->pts[i_pt+5]);
i_pt += 6;
break;
case dps_closepath:
PSclosepath();
break;
}
}
}
/*
* If the ucache is to be used then include the first operator
* otherwise skip it.
*/
static void strokeUpath(UPath *aUpath, int manner, int *strokes)
{
*strokes += 1;
if (manner == UCACHE)
DPSDoUserPath(&aUpath->pts[4], aUpath->num_pts - 4, dps_float,
&aUpath->ops[0], aUpath->num_ops, aUpath->pts, dps_ustroke);
else
DPSDoUserPath(&aUpath->pts[4], aUpath->num_pts - 4, dps_float,
&aUpath->ops[1], aUpath->num_ops-1, aUpath->pts, dps_ustroke);
}
/*
* Omit the bounding box numbers at the beginning of the operand
* array as well as the dps_ucache at the beginning of the operator
* array. Update the bounding box of the user path if necessary.
*/
- getUpath:(NXRect *) r fromGraphic:graphicId
{
int ops_before;
UPath *gUpath;
[graphicId getUpath:&gUpath forRect:r];
if (gUpath)
{
timing_info.num_subpaths++;
if (!drawCombined)
{
if (drawManner == REDBOOK)
{
makeRedBook(gUpath);
strokeRedBook(&timing_info.num_strokes);
}
else
strokeUpath(gUpath, drawManner, &timing_info.num_strokes);
}
else
{
if (drawUpath->num_pts + gUpath->num_pts > PTS_UPATH_BUFFER ||
drawUpath->num_ops + gUpath->num_ops > OPS_UPATH_BUFFER)
{
if (drawManner == REDBOOK)
strokeRedBook(&timing_info.num_strokes);
else
strokeUpath(drawUpath, drawManner, &timing_info.num_strokes);
initUpath(drawUpath);
}
if (drawManner == REDBOOK)
makeRedBook(gUpath);
else
{
bcopy(&gUpath->pts[4], &drawUpath->pts[drawUpath->num_pts],
(gUpath->num_pts - 4)* (sizeof(float)/sizeof(char)));
bcopy(&gUpath->ops[1], &drawUpath->ops[drawUpath->num_ops],
gUpath->num_ops-1);
drawUpath->pts[0] = MIN(gUpath->pts[0], drawUpath->pts[0]);
drawUpath->pts[1] = MIN(gUpath->pts[1], drawUpath->pts[1]);
drawUpath->pts[2] = MAX(gUpath->pts[2], drawUpath->pts[2]);
drawUpath->pts[3] = MAX(gUpath->pts[3], drawUpath->pts[3]);
}
drawUpath->num_pts += gUpath->num_pts-4;
drawUpath->num_ops += gUpath->num_ops-1;
}
}
return self;
}
/*
* Compare the bounds of the object with the rectangle to draw in order to
* eliminate unnecessary drawing. The modal session stuff is just to
* intercept the selection of the redraw button in the interface during
* a trace. (This stops the drawing. It's only check during a trace
* because the trace can be quite long.)
*/
- drawSelf:(NXRect *)r :(int) count
{
int i, num, ElapsedTime;
BOOL tracing;
GParms parms;
GParms *p_parms;
NXRect rect;
NXRect *p_rect;
NXModalSession theSession;
if (eraseFields)
{
[self eraseFields:self];
eraseFields = NO;
}
PSsetgray(NX_WHITE);
NXRectFill(r);
initGparms(&parms);
if (drawFrame)
{
parms.linewidth = 0.05;
initUpath(drawUpath);
}
else
{
if (drawEveryPath)
p_parms = NULL;
else
p_parms = &parms;
}
setGparms(&parms);
NXSetColor(parms.color);
if (drawEverything)
p_rect = NULL;
else
{
rect = *r;
rect.origin.x += drawOrigin.x;
rect.origin.y += drawOrigin.y;
p_rect = ▭
}
tracing = [NXApp tracing];
if (tracing)
{
[[NXApp redrawButton] setTitle:"STOP"];
[NXApp beginModalSession:&theSession for:[NXApp methodsWindow]];
DPSTraceContext(DPSGetCurrentContext(), YES);
}
PSgsave();
NXRectClip(r);
PStranslate(-drawOrigin.x, -drawOrigin.y);
PSWMarkTime (); NXPing();
num = [graphicsListId count];
for (i = 0; i < num; i++)
{
if (tracing && (i % MODALTRACE == 0))
if ([NXApp runDrawModalSession:&theSession] != NX_RUNCONTINUES)
break;
if (drawFrame)
[self getUpath:p_rect fromGraphic:[graphicsListId objectAt:i]];
else
[[graphicsListId objectAt:i] drawObject:p_rect currentParms:p_parms
withManner:drawManner timingInfo:&timing_info];
}
if (drawFrame && drawCombined)
{
if (drawManner == REDBOOK)
strokeRedBook(&timing_info.num_strokes);
else
strokeUpath(drawUpath, drawManner, &timing_info.num_strokes);
}
PSWReturnTime (&ElapsedTime);
PSgrestore();
if (tracing)
{
DPSTraceContext(DPSGetCurrentContext(), NO);
[NXApp endModalSession:&theSession];
[[NXApp redrawButton] setTitle:"redraw"];
}
timing_info.drawingtime += ElapsedTime;
++timing_info.num_draws;
if (displayFields)
{
[self displayFields:self];
displayFields = NO;
eraseFields = YES;
}
return self;
}
@end